home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / osrc.arc / DIRUTIL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-04-16  |  7.8 KB  |  381 lines

  1. /* dirutil.c - MS-DOS directory reading routines
  2.  *
  3.  * Bdale Garbee, N3EUA, Dave Trulli, NN2Z, and Phil Karn, KA9Q
  4.  * Directory sorting by Mike Chepponis, K3MC
  5.  * New version using regs.h by Russell Nelson.
  6.  * Rewritten for Turbo-C 2.0 routines by Phil Karn, KA9Q 25 March 89
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <dir.h>
  11. #include <dos.h>
  12. #include "global.h"
  13.  
  14. FILE *tmpfile();
  15. char *getcwd();
  16. void dir_sort(), free_clist();
  17. void format_fname_full(), print_free_space();
  18. char *wildcardize();
  19.  
  20. #define REGFILE    (FA_HIDDEN|FA_SYSTEM|FA_DIREC)
  21.  
  22. #define    insert_ptr(list,new)    (new->next = list,list = new)
  23.  
  24. struct dirsort {
  25.     struct dirsort *next;
  26.     struct ffblk de;
  27. };
  28. #define    NULLSORT (struct dirsort *)0
  29.  
  30. /* Create a directory listing in a temp file and return the resulting file
  31.  * descriptor. If full == 1, give a full listing; else return just a list
  32.  * of names.
  33.  */
  34. FILE *
  35. dir(path,full)
  36. char *path;
  37. int full;
  38. {
  39.     FILE *fp;
  40.  
  41.     fp = tmpfile();
  42.     getdir(path,full,fp);
  43.     rewind(fp);
  44.     return fp;
  45. }
  46.  
  47. /* find the first or next file and lowercase it. */
  48. int
  49. nextname(command, name, sbuf)
  50. int command;
  51. char *name;
  52. struct ffblk *sbuf;
  53. {
  54.     int found;
  55.  
  56.     switch(command){
  57.     case 0:
  58.         found = findfirst(name,sbuf,REGFILE);
  59.         break;
  60.     default:
  61.         found = findnext(sbuf);
  62.     }
  63.     found = found == 0;
  64.     if(found)
  65.         strlwr(sbuf->ff_name);
  66.  
  67.     return found;
  68. }
  69.  
  70. /* wildcard filename lookup */
  71. filedir(name,times,ret_str)
  72. char *name;
  73. int times;
  74. char *ret_str;
  75. {
  76.     static struct ffblk sbuf;
  77.     int rval;
  78.  
  79.     switch(times){
  80.     case 0:
  81.         rval = findfirst(name,&sbuf,REGFILE);
  82.         break;
  83.     default:
  84.         rval = findnext(&sbuf);
  85.         break;
  86.     }
  87.     if(rval == -1){
  88.         ret_str[0] = '\0';
  89.     } else {
  90.         /* Copy result to output */
  91.         strcpy(ret_str, sbuf.ff_name);
  92.     }
  93. }
  94. /* do a directory list to the stream 
  95.  * full = 0 -> short form, 1 is long
  96. */
  97. getdir(path,full,file)
  98. char *path;
  99. int full;
  100. FILE *file;
  101. {
  102.     struct ffblk sbuf;
  103.     int command = 0;
  104.     int n = 0;
  105.     struct dirsort *head, *here, *new;
  106.  
  107.     path = wildcardize(path);
  108.  
  109.     head = NULLSORT;    /* No head of chain yet... */
  110.     for(;;){
  111.         if (!nextname(command, path, &sbuf))
  112.             break;
  113.         command = 1;    /* Got first one already... */
  114.         if (sbuf.ff_name[0] == '.')    /* drop "." and ".." */
  115.             continue;
  116.  
  117.         new = (struct dirsort *) malloc(sizeof(struct dirsort));
  118.         if(new == NULLSORT){
  119.             /* Clean up and call other routine */
  120.             free_clist(head);
  121.             return getdir_nosort(path,full,file);
  122.         }
  123.         new->de = sbuf;    /* Copy contents of directory entry struct */
  124.  
  125.         /* insert it into the list */
  126.         if (!head || fncmp(new->de.ff_name, head->de.ff_name) < 0) {
  127.             insert_ptr(head, new);
  128.         } else {
  129.             register struct dirsort *this;
  130.             for (this = head;
  131.                 this->next != NULLSORT;
  132.                 this = this->next)
  133.                 if (fncmp(new->de.ff_name, this->next->de.ff_name) < 0)
  134.                     break;
  135.             insert_ptr(this->next, new);
  136.         }
  137.     } /* infinite FOR loop */
  138.  
  139.     for (here = head; here; here = here->next)
  140.         format_fname_full(file,&here->de,full,++n);
  141.  
  142.     /* Give back all the memory we temporarily needed... */
  143.     free_clist(head);
  144.  
  145.     if(full)
  146.         print_free_space(file, n);
  147.  
  148.     return 0;
  149. }
  150. int
  151. fncmp(a,b)
  152. register char *a, *b;
  153. {
  154.         int i;
  155.  
  156.     for(;;){
  157.         if (*a == '.')
  158.             return -1;
  159.         if (*b == '.')
  160.             return 1;
  161.         if ((i = *a - *b++) != 0)
  162.             return i;
  163.         if (!*a++)
  164.             return -1;
  165.     }
  166. }
  167. /* Change working directory */
  168. docd(argc,argv)
  169. int argc;
  170. char *argv[];
  171. {
  172.     char dirname[128];
  173.  
  174.     if(argc > 1){
  175.         if(chdir(argv[1]) == -1){
  176.             printf("Can't change directory\n");
  177.             return 1;
  178.         }
  179.     }
  180.     if(getcwd(dirname,128) != NULLCHAR){
  181.         undosify(dirname);
  182.         printf("%s\n",dirname);
  183.     }
  184.     return 0;
  185. }
  186. /* List directory to console */
  187. dodir(argc,argv)
  188. int argc;
  189. char *argv[];
  190. {
  191.     char *path;
  192.  
  193.     if(argc >= 2)
  194.         path = argv[1];
  195.     else
  196.         path = "*.*";
  197.  
  198.     getdir(path,1,stdout);
  199.     return 0;
  200. }
  201.  
  202.  
  203. /*
  204.  * Return a string with commas every 3 positions.
  205.  * If malloc() fails, return original string unmodified.
  206.  * else the original string is replace with the string with commas.
  207.  *
  208.  * The caller must be sure that there is enough room for the resultant
  209.  * string.
  210.  *
  211.  *
  212.  * k3mc 4 Dec 87
  213.  */
  214. void
  215. commas(dest)
  216. char *dest;
  217. {
  218.     char *src, *core;    /* Place holder for malloc */
  219.     unsigned cc;        /* The comma counter */
  220.     unsigned len;
  221.  
  222.     len = strlen(dest);
  223.     /* Make a copy, so we can muck around */
  224.     if( (core = src = strdup(dest)) == NULLCHAR)
  225.         return;
  226.  
  227.     cc = (len-1)%3 + 1;    /* Tells us when to insert a comma */
  228.  
  229.     while(*src != '\0'){
  230.         *dest++ = *src++;
  231.         if( ((--cc) == 0) && *src ){
  232.             *dest++ = ','; cc = 3;
  233.         }
  234.     }
  235.     free(core);
  236.     *dest = '\0';
  237. }
  238. /* fix up the filename so that it contains the proper wildcard set */
  239. char *
  240. wildcardize(path)
  241. char *path;
  242. {
  243.     struct ffblk sbuf;
  244.     static char ourpath[64];
  245.  
  246.     /* Root directory is a special case */
  247.     if(path == NULLCHAR ||
  248.        *path == '\0' ||
  249.        strcmp(path,"\\") == 0 ||
  250.        strcmp(path,"/") == 0)
  251.         path = "\\*.*";
  252.  
  253.     /* if they gave the name of a subdirectory, append \*.* to it */
  254.     if (nextname(0, path, &sbuf) &&
  255.         (sbuf.ff_attrib & FA_DIREC) &&
  256.         !nextname(1, path, &sbuf)) {
  257.  
  258.         /* if there isn't enough room, give up -- it's invalid anyway */
  259.         if (strlen(path) + 4 > 63) return path;
  260.         strcpy(ourpath, path);
  261.         strcat(ourpath, "\\*.*");
  262.         return ourpath;
  263.     }
  264.     return path;
  265. }
  266.  
  267. void
  268. format_fname_full(file, sbuf, full, n)
  269. FILE *file;
  270. struct ffblk *sbuf;
  271. int full, n;
  272. {
  273.     char line_buf[50];        /* for long dirlist */
  274.     char cbuf[20];            /* for making line_buf */
  275.  
  276.     strcpy(cbuf,sbuf->ff_name);
  277.     if(sbuf->ff_attrib & FA_DIREC) strcat(cbuf, "/");
  278.     if (full) {
  279.         /* Long form, give other info too */
  280.         sprintf(line_buf,"%-13s",cbuf);
  281.         if(sbuf->ff_attrib & FA_DIREC)
  282.             strcat(line_buf,"           ");/* 11 spaces */
  283.         else {
  284.             sprintf(cbuf,"%ld",sbuf->ff_fsize);
  285.             commas(cbuf);
  286.             sprintf(line_buf+strlen(line_buf),"%10s ",cbuf);
  287.         }
  288.         sprintf(line_buf+strlen(line_buf),"%2d:%02d %2d/%02d/%02d%s",
  289.           (sbuf->ff_ftime >> 11) & 0x1f,    /* hour */
  290.           (sbuf->ff_ftime >> 5) & 0x3f,    /* minute */
  291.           (sbuf->ff_fdate >> 5) & 0xf,    /* month */
  292.           (sbuf->ff_fdate ) & 0x1f,        /* day */
  293.           (sbuf->ff_fdate >> 9) + 80,    /* year */
  294.           (n & 1) ? "   " : "\n");
  295.         fputs(line_buf,file);
  296.     } else {
  297.         fputs(cbuf,file);
  298.         fputs("\n",file);
  299.     }
  300. }
  301. /* Provide additional information only on DIR */
  302. void
  303. print_free_space(file, n)
  304. FILE *file;
  305. int n;
  306. {
  307.     unsigned long free_bytes, total_bytes;
  308.     char s_free[11], s_total[11];
  309.     char cbuf[20];
  310.     struct dfree dtable;
  311.     unsigned long bpcl;
  312.  
  313.     if(n & 1)
  314.         fputs("\r\n",file);
  315.  
  316.     /* Find disk free space */
  317.     getdfree(0,&dtable);
  318.  
  319.     bpcl = dtable.df_bsec * dtable.df_sclus;
  320.     free_bytes  = dtable.df_avail * bpcl;
  321.     total_bytes = dtable.df_total * bpcl;
  322.  
  323.     sprintf(s_free,"%ld",free_bytes);
  324.     commas(s_free);
  325.     sprintf(s_total,"%ld",total_bytes);
  326.     commas(s_total);
  327.  
  328.     if(n)
  329.         sprintf(cbuf,"%d",n);
  330.     else
  331.         strcpy(cbuf,"No");
  332.  
  333.     fprintf(file,"%s file%s. %s bytes free. Disk size %s bytes.\n",
  334.         cbuf,(n==1? "":"s"),s_free,s_total);
  335. }
  336. void
  337. free_clist(this)
  338. struct dirsort *this;
  339. {
  340.     struct dirsort *next;
  341.  
  342.     while (this != NULLSORT) {
  343.         next = this->next;
  344.         free(this);
  345.         this = next;
  346.     }
  347. }
  348. getdir_nosort(path,full,file)
  349. char *path;
  350. int full;
  351. FILE *file;
  352. {
  353.     struct ffblk sbuf;
  354.     int command;
  355.     int n = 0;    /* Number of directory entries */
  356.     void format_fname_full(), print_free_space();
  357.  
  358.     path = wildcardize(path);
  359.     command = 0;
  360.     while(nextname(command, path, &sbuf)){
  361.         command = 1;    /* Got first one already... */
  362.         if (sbuf.ff_name[0] == '.')    /* drop "." and ".." */
  363.             continue;
  364.         format_fname_full(file, &sbuf, full, ++n);
  365.     }
  366.     if(full)
  367.         print_free_space(file, n);
  368.     return 0;
  369. }
  370.  
  371. /* Translate those %$#@!! backslashes to proper form */
  372. undosify(s)
  373. char *s;
  374. {
  375.     while(*s != '\0'){
  376.         if(*s == '\\')
  377.             *s = '/';
  378.         s++;
  379.     }
  380. }
  381.